#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

"""
@File    : chart_trans_bar_sample.py
@Author  : Link
@Time    : 2023/4/22 12:52
@Mark    :
    虚拟分布功能, 就是使用简单的分布工具
    1. 导入Limit数据, 自定义参数来修改分布
        1.1 相关显示
    2. 自动顺序转入到dtp数据集中
    3. 数据重算
"""
from dataclasses import dataclass
from typing import Union

import numpy as np
import pandas as pd
from pyqtgraph import InfiniteLine, BarGraphItem

from chart_core.chart_pyqtgraph.core.mixin import PlotWidget
from chart_core.chart_pyqtgraph.core.view_box import CustomViewBox
from chart_core.chart_pyqtgraph.ui_components.ui_unit_chart import UnitChartWindow
from common.data_class_interface.for_analysis_stdf import DTP_HEAD


@dataclass
class NormalSampleBarParams:
    """
    简单的正态分布模型
    """
    TITLE: str
    HI_LIMIT: float
    LO_LIMIT: float
    LOC: float  # 偏移 -> 期望
    SCALE: float  # 缩放参数 -> 标准差
    NUMS: int  # TODO: 注意不要被修改, 不然写入Dtp一定会报错
    BINS: int


@dataclass
class DtpSampleBarParams:
    """
    Dtp数据加减模型
    """
    TITLE: str
    HI_LIMIT: float
    LO_LIMIT: float
    LOC: float  # 偏移 -> +-
    NUMS: int  # TODO: 注意不要被修改, 不然一定会报错
    BINS: int
    DF: pd.DataFrame  # Dtp


class TransBarChartSample(UnitChartWindow):
    """
    简单一些, 只有一个bg, 没有ticks
    """

    def __init__(self):
        super(TransBarChartSample, self).__init__()

        self.vb = CustomViewBox()
        self.pw = PlotWidget(viewBox=self.vb, enableMenu=False)
        self.setCentralWidget(self.pw)
        self.pw.hideButtons()

        self.bg1 = BarGraphItem(x0=[], y=[], y0=[], y1=[], width=[])

        self.pw.addItem(self.bg1)
        self.pw.setMouseEnabled(x=False, y=False)

    def set_df_chart(self, param: Union[NormalSampleBarParams, DtpSampleBarParams]):
        """
        根据参数显示虚拟分布数据
        :return:
        """

        self.pw.plotItem.setTitle(param.TITLE)
        serials = None
        if isinstance(param, NormalSampleBarParams):
            serials = np.random.normal(loc=param.LOC, scale=param.SCALE, size=param.NUMS)
        if isinstance(param, DtpSampleBarParams):
            serials = param.DF[DTP_HEAD.RESULT] + param.LOC
        if serials is None:
            return
        list_bins = np.linspace(param.LO_LIMIT, param.HI_LIMIT, param.BINS)
        step = (param.HI_LIMIT - param.LO_LIMIT) / param.BINS

        columns, x0, y0, y1, y, width, bar_width = [], [], [], [], [], [], 0
        temp_dis = pd.Series(serials).value_counts(bins=list_bins, sort=False)

        for bin_index, value in enumerate(temp_dis.values):
            x0.append(0.2)
            y0.append(list_bins[bin_index])
            y1.append(list_bins[bin_index + 1])
            y.append((list_bins[bin_index + 1] + list_bins[bin_index]) / 2)
            width.append(value)
        # x0 = np.array(x0) * max(temp_dis)
        self.bg1.setOpts(x0=x0, y=y, y0=y0, y1=y1, width=width, brush=(217, 83, 25, 255))
        self.vb.setYRange(param.LO_LIMIT - 3 * step, param.HI_LIMIT + 3 * step)
        self.vb.setXRange(max(temp_dis) * -0.2, max(temp_dis) * 1.2)

        inf = InfiniteLine(
            movable=False, angle=0, pen=(255, 0, 0), hoverPen=(0, 0, 0),
            label="LO_LIMIT", labelOpts={'color': (0, 0, 200), 'position': 0.1}
        )
        inf.setPos(param.LO_LIMIT)
        self.pw.addItem(inf)

        inf = InfiniteLine(
            movable=False, angle=0, pen=(255, 0, 0), hoverPen=(0, 0, 0),
            label="HI_LIMIT", labelOpts={'color': (0, 0, 200), 'position': 0.1}
        )
        inf.setPos(param.HI_LIMIT)
        self.pw.addItem(inf)
        avg = np.average(serials)
        inf = InfiniteLine(
            movable=False, angle=0, pen=(255, 0, 0), hoverPen=(0, 0, 0),
            label="AVG:%.9f" % avg, labelOpts={'color': (0, 0, 200), 'position': 0.1}
        )
        inf.setPos(avg)
        self.pw.addItem(inf)
